#include "validator.h"

#include <boost/regex.hpp>

#include "xml/XMLParse.h"
#include "dtd/DTDParse.h"

using namespace std;
using namespace boost;

static bool xml_valid(Element* xml, DTD* dtd) {
    static map<string,regex>regexs = dtd->toRegExp();
    return xml->validationWithDTD(&regexs);    
}

/**
 * À partir du chemin d'un fichier xml et du nom de la feuille DTD,
 * retrouve le chemin du fichier DTD (en supposant qu'elle est dans
 * le même dossier que le fichier XML
 */
static string find_dtd_path(string xml_path, string dtd_name)
{
    if (dtd_name[0] == '/') // Chemin absolu
        return dtd_name;
    else                  // Chemin relatif
        return xml_path.substr(0, xml_path.find_last_of("/\\")+1) + dtd_name;
}


validate_state validate_xml(string xml_path, string dtd_path = "") {
	Element* document;
	DTD* dtd_doc;
	string default_dtd_path; // Nom fichier DTD donné dans le fichier XML
	char *c_default_dtd_path; // idem (temporaire pour bison)
	xmlin = NULL;
	dtdin = NULL;
	
	xmlin = fopen(xml_path.c_str(), "r");
	if (xmlin == NULL)
		return XML_NOT_FOUND;
	
	if (xmlparse(&document, &c_default_dtd_path) != 0)
		return XML_INVALID;

	default_dtd_path = string(c_default_dtd_path);
	if (dtd_path == "" && default_dtd_path == "")
		return XML_VALID;
	
	if (dtd_path == "" )
		dtd_path = find_dtd_path(xml_path, default_dtd_path);

	dtdin = fopen(dtd_path.c_str(), "r");
	if (dtdin == NULL)
		return DTD_NOT_FOUND;
	
	if (dtdparse(&dtd_doc) != 0)
		return DTD_INVALID;
	
	if (!xml_valid(document, dtd_doc))
		return XML_NOT_CONFORM;

	return OK;
}
